/*************************************************************************
** Name		: CrypUtil.h
** Desc		: 简单加密类。如果需要更复杂的类可去movcrypto工程里找。
** Author	: xktesla
*************************************************************************/

#ifndef _E688D93B_6A80_4198_B155_5271A569E14A
#define _E688D93B_6A80_4198_B155_5271A569E14A

#include "depends/incfile.h"

namespace x2lib
{
	class CrypUtil
	{
    public:
        /**
        * @brief        计算32位Md5
        * @param[in]    pData 待加密的数据
        * @param[in]    nData 待加密的数据长度
        * @param[out]   buff 保存结果的缓冲区，若nullptr则使用函数内静态内存保存，此时多线程不安全
        * @return       返回所得值，如：07775c1e37bef69b42ffb25eace5c3f2
        * @author       xktesla
        */
		static const char* Md5(const uint8_t* pData, int nData, char buff[64] = nullptr);

        // 计算32位Md5，字符串版
        static const char* Md5(const char* s, char buff[64] = nullptr);

        /**
        * @brief        Base64编解码
        * @param[in]    pData 待处理数据指针
        * @param[in]    nData 待处理数据长度
        * @param[in]    pDataout 存放结果的指针，请自行确保长度够用
        * @param[in]    pnDataout 存放计算后的数据长度的指针
        * @param[in]    isEncrypt true编码，false解码
        * @return       返回结果，地址值等同于pDataout
        * @author       xktesla
        */
        static void* Base64(void* pData, int nData, void* pDataout, int* pnDataout, bool isEncrypt = true);

        /**
        * @brief        简单异或加密，处理前后数据长度不变
        * @param[in]    pIn 待加密数据指针
        * @param[in]    pOut 存放加密后的数据的指针
        * @param[in]    nLen 数据长度，
        * @param[in]    uKey 秘钥
        * @return       返回加密后的数据指针，等同于pOut
        * @author       xktesla
        */
        static void* Encrypt(void* pIn, void* pOut, uint32_t nLen, uint8_t uKey);

        /**
        * @brief        简单异或解密（实现逻辑与Encrypt等价），处理前后数据长度不变
        * @param[in]    pIn 待解密数据指针
        * @param[in]    pOut 存放解密后的数据的指针
        * @param[in]    nLen 数据长度
        * @param[in]    uKey 秘钥
        * @return       返回解密后的数据指针，等同于pOut
        * @author       xktesla
        */
        static void* Decrypt(void* pIn, void* pOut, uint32_t nLen, uint8_t uKey);

        /**
        * @brief        依次异或加密；将pIn第nLen-1个元素用uKey异或，将pIn第nLen-2个元素用pIn[nLen-1]异或，依次类推
        * @param[in]    pIn 待加密数据指针
        * @param[in]    pOut 存放加密后的数据的指针
        * @param[in]    nLen 数据长度
        * @param[in]    uKey 秘钥
        * @return       返回加密后的数据指针，等同于pOut
        * @author       xktesla
        */
        static void* Encrypt1(void* pIn, void* pOut, uint32_t nLen, uint8_t uKey);

        /**
        * @brief        依次异或解密；将pIn[0]用第pIn[1]异或，将pIn[1]用pIn[2]异或，依次类推到pIn[nLen-1]，用uKey异或
        * @param[in]    pIn 待解密数据指针
        * @param[in]    pOut 存放解密后的数据的指针
        * @param[in]    nLen 数据长度
        * @param[in]    uKey 秘钥
        * @return       返回解密后的数据指针，等同于pOut
        * @author       xktesla
        */
        static void* Decrypt1(void* pIn, void* pOut, uint32_t nLen, uint8_t uKey);

        /**
        * @brief        Encrypt1增强版
        * @author       xktesla@2022-4-22 08:18:42 coding 待验证
        */
        static void* Encrypt2(void* pIn, void* pOut, uint32_t nLen, const char* szPwd);

        /**
        * @brief        Decrypt1增强版
        * @author       xktesla@2022-4-22 08:18:42 coding 待验证
        */
        static void* Decrypt2(void* pIn, void* pOut, uint32_t nLen, const char* szPwd);

        static uint32_t CalcCrc32(void* pData, uint32_t nData);
	};
}

#endif
